package auth

import (
	"errors"
	"time"

	"github.com/dgrijalva/jwt-go"
)

type Claims struct {
	UserID   string `json:"user_id"`
	UserName string `json:"user_name"`
	jwt.StandardClaims
}

type JWTConfig struct {
	SecretKey          string
	ExpiresTime        int64
	Issuer             string
	BufferTime         int64
	BlacklistKeyPrefix string
}

type JWTAuth struct {
	config JWTConfig
}

func NewJWTAuth(config JWTConfig) *JWTAuth {
	return &JWTAuth{config: config}
}

// GenerateToken 生成JWT token
func (j *JWTAuth) GenerateToken(userID, userName string) (string, error) {
	claims := Claims{
		UserID:   userID,
		UserName: userName,
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: time.Now().Unix() + j.config.ExpiresTime,
			Issuer:    j.config.Issuer,
		},
	}

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return token.SignedString([]byte(j.config.SecretKey))
}

// ParseToken 解析JWT token
func (j *JWTAuth) ParseToken(tokenString string) (*Claims, error) {
	token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
		return []byte(j.config.SecretKey), nil
	})

	if err != nil {
		return nil, err
	}

	if claims, ok := token.Claims.(*Claims); ok && token.Valid {
		return claims, nil
	}

	return nil, errors.New("invalid token")
}
